package com.witmore.neutron.ai.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.witmore.neutron.ai.db.entity.RoleDO;
import com.witmore.neutron.ai.db.entity.RoleUserDO;
import com.witmore.neutron.ai.db.mapper.RoleMapper;
import com.witmore.neutron.ai.db.mapper.RoleUserMapper;
import com.witmore.neutron.ai.web.enums.RoleTypeEnum;
import com.witmore.neutron.ai.web.service.UserRoleBindingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 用户角色绑定服务实现类
 * 
 * @author 豆子高
 * @date 2025/1/2
 */
@Slf4j
@Service
public class UserRoleBindingServiceImpl implements UserRoleBindingService {

    @Autowired
    private RoleUserMapper roleUserMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bindNormalUserRole(Long userId, Long providerId) {
        try {
            // 检查用户是否已有角色绑定
            if (hasRoleBinding(userId)) {
                log.info("用户{}已有角色绑定，跳过普通用户角色绑定", userId);
                return;
            }

            // 绑定普通用户角色
            bindUserRole(userId, providerId != null ? providerId : 0L, RoleTypeEnum.NORMAL_USER, "普通用户");
        } catch (Exception e) {
            log.error("为用户{}绑定普通用户角色异常", userId, e);
            throw e;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bindServiceProviderAdminRole(Long userId, Long providerId) {
        try {
            // 检查是否已经有相同的服务商管理员角色绑定
            if (hasSpecificRoleBinding(userId, providerId, RoleTypeEnum.SERVICE_PROVIDER_ADMIN)) {
                log.info("用户{}已有服务商{}的管理员角色绑定，跳过绑定", userId, providerId);
                return;
            }

            // 绑定服务商管理员角色
            bindUserRole(userId, providerId, RoleTypeEnum.SERVICE_PROVIDER_ADMIN, "服务商管理员");
        } catch (Exception e) {
            log.error("为用户{}绑定服务商{}管理员角色异常", userId, providerId, e);
            throw e;
        }
    }

    /**
     * 绑定用户角色的通用方法
     * @param userId 用户ID
     * @param providerId 服务商ID
     * @param roleType 角色类型枚举
     * @param roleDescription 角色描述（用于日志）
     */
    private void bindUserRole(Long userId, Long providerId, RoleTypeEnum roleType, String roleDescription) {
        // 查询角色
        RoleDO role = getRoleByType(roleType);
        
        // 创建角色用户绑定关系
        RoleUserDO roleUserDO = createRoleUserDO(userId, role.getId(), providerId);
        
        // 插入数据库
        int result = roleUserMapper.insert(roleUserDO);
        if (result > 0) {
            log.info("成功为用户{}绑定{}角色，角色ID：{}，服务商ID：{}", userId, roleDescription, role.getId(), providerId);
        } else {
            log.error("为用户{}绑定{}角色失败", userId, roleDescription);
            throw new RuntimeException("角色绑定失败");
        }
    }

    /**
     * 根据角色类型查询角色
     * @param roleType 角色类型枚举
     * @return 角色实体
     */
    private RoleDO getRoleByType(RoleTypeEnum roleType) {
        RoleDO role = roleMapper.selectOne(
            new LambdaQueryWrapper<RoleDO>()
                .eq(RoleDO::getRoleType, roleType.getCode())
                .eq(RoleDO::getIsDeleted, 0)
        );

        if (role == null) {
            log.error("未找到{}角色，角色类型：{}", roleType.getDescription(), roleType.getCode());
            throw new RuntimeException("系统角色配置错误：未找到" + roleType.getDescription() + "角色");
        }

        return role;
    }

    /**
     * 创建角色用户绑定关系对象
     * @param userId 用户ID
     * @param roleId 角色ID
     * @param providerId 服务商ID
     * @return 角色用户绑定关系对象
     */
    private RoleUserDO createRoleUserDO(Long userId, Long roleId, Long providerId) {
        RoleUserDO roleUserDO = new RoleUserDO();
        roleUserDO.setUserId(userId);
        roleUserDO.setRoleId(roleId);
        roleUserDO.setProviderId(providerId);
        roleUserDO.setCreator("system");
        roleUserDO.setCreateTime(LocalDateTime.now());
        roleUserDO.setUpdateTime(LocalDateTime.now());
        return roleUserDO;
    }

    /**
     * 检查用户是否已有特定的角色绑定
     * @param userId 用户ID
     * @param providerId 服务商ID
     * @param roleType 角色类型枚举
     * @return 是否已有绑定
     */
    private boolean hasSpecificRoleBinding(Long userId, Long providerId, RoleTypeEnum roleType) {
        try {
            RoleDO role = getRoleByType(roleType);
            
            RoleUserDO existingBinding = roleUserMapper.selectOne(
                new LambdaQueryWrapper<RoleUserDO>()
                    .eq(RoleUserDO::getUserId, userId)
                    .eq(RoleUserDO::getRoleId, role.getId())
                    .eq(RoleUserDO::getProviderId, providerId)
            );

            return existingBinding != null;
        } catch (Exception e) {
            log.error("检查用户{}特定角色绑定异常", userId, e);
            return false;
        }
    }

    @Override
    public boolean hasRoleBinding(Long userId) {
        try {
            Long count = roleUserMapper.selectCount(
                new LambdaQueryWrapper<RoleUserDO>()
                    .eq(RoleUserDO::getUserId, userId)
            );
            return count > 0;
        } catch (Exception e) {
            log.error("检查用户{}角色绑定异常", userId, e);
            return false;
        }
    }
}